// ============================================================================
// Name        : SYScalls.S
// Authors     : Galli, Nadia
// 		 Pivetta, Agustin
// 		 Tkaczyszyn, Facundo
// Version     : 1.0
// Description : Tp1 66.20: Programacion MIPS
// ============================================================================
// Inicio del codigo
#include <mips/regdef.h>
#include <sys/syscall.h>

.text
.align 2
// ============================================================================
// Esta funcion es la equivalente a write() de C
// size_t write_asm(int handle, void *buffer, int nbyte);

// Diagrama de Stack
// 40 - [  a2  ]
// 36 - [  a1  ]
// 32 - [__a0__]_____________________
// 28 - [  pad ]
// 24 - [  ra  ] Saved Register Area
// 20 - [  fp  ]
// 16 - [  gp  ]_____________________
// 12 - [      ] 
// 8  - [      ] Argument Building
// 4  - [      ] Area
// 0  - [      ]_____________________

.globl write_asm
.ent write_asm

write_asm:
        .frame $fp,32,ra
	.set noreorder
	.cpload t9
	.set reorder
    
        // creo stack frame
        subu sp,sp,32   	#Reservo 32 Bytes (16 para parametros, 16 para respaldar los valores de fp, gp y ra)
        .cprestore 16

        sw ra,24(sp) 		#Respaldo la posicion de la return address
        sw $fp,20(sp) 		#Respaldo la posicion del frame pointer
	sw gp,16(sp)		#Respaldo la posicion del global pointer
	move $fp,sp
        sw a0,32($fp)		# guardo el argumento 0 en el ABA del caller
	sw a1,36($fp)		# guardo el argumento 1 en el ABA del caller
	sw a2,40($fp)		# guardo el argumento 2 en el ABA del caller
	li v1, 0	
	li v0, 0    

	li v0,SYS_write 	# Los argumentos ya vienen cargados en el correcto orden desde la llamada
	syscall

	bne a3,zero,write_error	#Ocurrio un error en la escritura
	beq a3,zero,write_exit
    
write_error:
	move v0,zero
	addi v1,zero,2		#Pongo a v1 en 2 para indicar error de escritura

write_exit:
	lw ra,24(sp)		#Recupero la posicion de la return address
	lw $fp,20(sp)		#Recupero la posicion del frame pointer
	lw gp,16(sp)		#Recupero la posicion del global pointer
	addu sp,sp,32
	j ra

.end write_asm

// ============================================================================
// Esta funcion es la equivalente a read() de C
// size_t read_asm(int handle, void *buffer, int nbyte);

// Diagrama de Stack
// 40 - [  a2  ]
// 36 - [  a1  ]
// 32 - [__a0__]_____________________
// 28 - [  pad ]
// 24 - [  ra  ] Saved Register Area
// 20 - [  fp  ]
// 16 - [  gp  ]_____________________
// 12 - [      ] 
// 8  - [      ] Argument Building
// 4  - [      ] Area
// 0  - [      ]_____________________

.globl read_asm
.ent read_asm

read_asm:
        .frame $fp,32,ra
	.set noreorder
	.cpload t9
	.set reorder
    
        // creo stack frame
        subu sp,sp,32   #Reservo 32 Bytes (16 para parametros, 16 para respaldar los valores de fp y gp)
        .cprestore 16

        sw ra,24(sp) 		#Respaldo la posicion de la return address
        sw $fp,20(sp) 		#Respaldo la posicion del frame pointer
	sw gp,16(sp)		#Respaldo la posicion del global pointer
	move $fp,sp
        sw a0,32($fp)		# guardo el argumento 0 en el ABA del caller
	sw a1,36($fp)		# guardo el argumento 1 en el ABA del caller
	sw a2,40($fp)		# guardo el argumento 2 en el ABA del caller+
	li v1, 0	
	li v0, 0    

	li v0,SYS_read 		# Los argumentos ya vienen cargados en el correcto orden desde la llamada
	syscall

	bne a3,zero,read_error	#Ocurrio un error en la lectura
	beq a3,zero,read_exit
    
read_error:
	move v0,zero
	addi v1,zero,1		#Pongo a v1 en 1 para indicar error en la lectura	

read_exit:
	lw ra,24(sp)		#Recupero la posicion de la return address
	lw $fp,20(sp)		#Recupero la posicion del frame pointer
	lw gp,16(sp)		#Recupero la posicion del global pointer
	addu sp,sp,32
	j ra

.end read_asm
